package com.ysyx.ysyx_shareorder.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ysyx.ysyx_shareorder.dto.BaseDto;
import com.ysyx.ysyx_shareorder.mapper.OrderdetailPojoMapper;
import com.ysyx.ysyx_shareorder.pojo.OrderPojo;
import com.ysyx.ysyx_shareorder.qo.GeoQo;
import com.ysyx.ysyx_shareorder.qo.TakeOrderQo;
import com.ysyx.ysyx_shareorder.service.OrderPojoService;
import com.ysyx.ysyx_shareorder.mapper.OrderPojoMapper;
import com.ysyx.ysyx_shareorder.util.MapToBeanUtils;
import org.redisson.api.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

/**
* @author 薛宇晖
* @description 针对表【order_inf(订单表)】的数据库操作Service实现
* @createDate 2023-04-11 14:20:40
*/
@Service
public class OrderPojoServiceImpl
    implements OrderPojoService{

    @Autowired
    private RedissonClient redissonClient;


    @Autowired
    private OrderPojoMapper orderPojoMapper;

    @Autowired
    private OrderdetailPojoMapper orderdetailPojoMapper;


    public BaseDto queryIsRob(GeoQo qo) throws Exception {
        System.out.println(qo);
        String areaName = "";

        List<RMap<Object,Object>> maps = new ArrayList<>();


        RMap<Object, Object> mapA1 = redissonClient.getMap("area:A1");
        RMap<Object, Object> mapA2 = redissonClient.getMap("area:A2");
        RMap<Object, Object> mapA3 = redissonClient.getMap("area:A3");
        RMap<Object, Object> mapB1 = redissonClient.getMap("area:B1");
        RMap<Object, Object> mapB2 = redissonClient.getMap("area:B2");
        RMap<Object, Object> mapB3 = redissonClient.getMap("area:B3");
        maps.add(mapA1);
        maps.add(mapA2);
        maps.add(mapA3);
        maps.add(mapB1);
        maps.add(mapB2);
        maps.add(mapB3);

        //判断司机的位置
        for (RMap<Object, Object> map : maps) {

            Double leftupLongitude = Double.parseDouble((String) map.get("leftupLongitude")) ;
            Double leftupLatitude = Double.parseDouble((String) map.get("leftupLatitude")) ;
            Double rightdownLongitude = Double.parseDouble((String) map.get("rightdownLongitude")) ;
            Double rightdownLatitude = Double.parseDouble((String) map.get("rightdownLatitude")) ;
            if (qo.getLongitude()>=leftupLongitude &&   //司机位置经度 >= 区域左上经度
                    qo.getLongitude()<=rightdownLongitude &&  //司机位置经度 <= 区域右下经度
                    qo.getLatitude()>=rightdownLatitude &&// 司机位置纬度 >= 区域右下纬度
                    qo.getLatitude()<=leftupLatitude// 司机位置纬度 >= 区域左上纬度
            )
            {
                areaName =  map.getName();
                break;
            }else {
                continue;
            }


        }
        //已经过去地区名称

        RGeo<String> geo = redissonClient.getGeo(areaName+":orders");

        List<String> radius = geo.radius(qo.getLongitude(),qo.getLatitude(), 5000, GeoUnit.METERS);

        List<OrderPojo> pojos = new ArrayList<>();
        //返回一个可接单的订单list
        int count = 5;
        for (String s : radius) {
            if (count<0){
                break;
            }
            count--;
            RMap<Object, Object> orderMap = redissonClient.getMap("orderinfo:" + s);
            System.err.println(s);
            System.out.println("我尝试打印");
            OrderPojo o = new OrderPojo();
            o.setOrderId((String) orderMap.get("orderId"));
            o.setPassengerId(Integer.valueOf((String) orderMap.get("passengerId")));
            o.setOrderStatus(Integer.valueOf((String) orderMap.get("orderStatus")));
            o.setOrderCost((Double.parseDouble((String) orderMap.get("orderCost"))));
            o.setOrderMileage((Double.parseDouble((String) orderMap.get("orderMileage"))) );
//            o.setDriverId((Integer.valueOf((String) orderMap.get("driverId"))));
            o.setStartName((String) orderMap.get("startName"));
            o.setEndName((String) orderMap.get("endName"));
//            (Date) orderMap.get("orderStatustime")
//            new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2019-01-03 10:59:27")

            o.setOrderStatustime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse((String)orderMap.get("orderStatustime")));
            o.setOrderStatus((Integer.valueOf((String) orderMap.get("orderStatus"))));


            pojos.add(o);
        }

        //判断订单长度
        BaseDto baseDto;

        if (pojos.size()==0){
            baseDto = new BaseDto(101,"附近没有订单",null);
            return baseDto;
        }

        baseDto = new BaseDto(201,"这是附近的订单",pojos);
        return  baseDto;
    }





    @DS("track_1")
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public List<OrderPojo> test92(){
        QueryWrapper queryWrapper = new QueryWrapper();
//        queryWrapper.eq("order_id",1);
        List<OrderPojo> pojos = orderPojoMapper.selectList(queryWrapper);
        System.err.println("让我测测");
        System.err.println(pojos);

        return pojos;
    }

    /*
     * @Description: (作用)
     * @params: qo   driverId 经纬度
     * @return:
     * @Author: 薛宇晖
     * @create:2023/4/14
     */
    @Override
    public BaseDto rapeOrder(GeoQo qo) {
        if (qo==null) {
            return new BaseDto(103,"杰荣你知道我要说什么",null);
        }

        BaseDto baseDto = new BaseDto();

        String areaName = "";

        List<RMap<Object,Object>> maps = new ArrayList<>();


        RMap<Object, Object> mapA1 = redissonClient.getMap("area:A1");
        RMap<Object, Object> mapA2 = redissonClient.getMap("area:A2");
        RMap<Object, Object> mapA3 = redissonClient.getMap("area:A3");
        RMap<Object, Object> mapB1 = redissonClient.getMap("area:B1");
        RMap<Object, Object> mapB2 = redissonClient.getMap("area:B2");
        RMap<Object, Object> mapB3 = redissonClient.getMap("area:B3");
        maps.add(mapA1);
        maps.add(mapA2);
        maps.add(mapA3);
        maps.add(mapB1);
        maps.add(mapB2);
        maps.add(mapB3);




        //判断司机的位置
        for (RMap<Object, Object> map : maps) {

            RGeo<Object> geo = redissonClient.getGeo(map.getName() + ":orders");
            if (geo.size()==0) {
                continue;
            }

            qo.setLongitude(geo.pos(qo.getOrderId()).get(qo.getOrderId()).getLongitude());
            qo.setLatitude(geo.pos(qo.getOrderId()).get(qo.getOrderId()).getLatitude());
            System.err.println(qo);

            Double leftupLongitude = Double.parseDouble((String) map.get("leftupLongitude")) ;
            Double leftupLatitude = Double.parseDouble((String) map.get("leftupLatitude")) ;
            Double rightdownLongitude = Double.parseDouble((String) map.get("rightdownLongitude")) ;
            Double rightdownLatitude = Double.parseDouble((String) map.get("rightdownLatitude")) ;
            if (qo.getLongitude()>=leftupLongitude &&   //司机位置经度 >= 区域左上经度
                    qo.getLongitude()<=rightdownLongitude &&  //司机位置经度 <= 区域右下经度
                    qo.getLatitude()>=rightdownLatitude &&// 司机位置纬度 >= 区域右下纬度
                    qo.getLatitude()<=leftupLatitude// 司机位置纬度 >= 区域左上纬度
            )
            {
                areaName =  map.getName();
                break;
            }else {
                continue;
            }


        }
        //已经过去地区名称 存在的司机

        RGeo<String> geo = redissonClient.getGeo(areaName+":drivers");

        List<String> radius = geo.radius(qo.getLongitude(),qo.getLatitude(), 6000, GeoUnit.METERS);

        if (radius.size()==0){
            //附近没有司机
            baseDto = new BaseDto(102,"附近没有司机~",null);
            return baseDto;
        }

        //获取到第一个键的名称  即driverId  给他撮合到订单
        String driverId = "";
        int count = 1;

        for (String s : radius) {
            count++;
            driverId = s;
            System.err.println("派单"+driverId);
            //去尝试移动司机出 上工司机待命池   work:driver:driverId  ==> working:driver set
            boolean delUnwork = redissonClient.getBucket("work:driver:" + driverId).delete();
            System.err.println(delUnwork);
            if (!delUnwork) {
                //判断以及找司机的次数
                if (count>10){
                    baseDto = new BaseDto(102,"系统繁忙,找不到合适的司机",null);
                    return baseDto;
                }
                System.err.println(driverId+"不在待命");
                continue;
            }
            //添加到工作中司机池  防止司机同时接两单
            boolean addWorking = redissonClient.getSet("working:driver").add(driverId);
            if (!addWorking) {
                if (count>10){
                    baseDto = new BaseDto(102,"系统繁忙,找不到合适的司机",null);
                    return baseDto;
                }
                System.err.println(driverId+"也已经在工作了");
                continue;
            }

            //尝试删除
            boolean delUnorder = redissonClient.getBucket("pend:order:" + qo.getOrderId()).delete();
            if (!delUnorder) {
                if (count>10){
                    baseDto = new BaseDto(102,"系统繁忙,找不到合适的司机",null);
                    return baseDto;
                }
               continue;
            }

            //添加到行程中订单池
            boolean tense = redissonClient.getSet("tense:order").add(qo.getOrderId());
            if (!tense) {
                if (count>10){
                    baseDto = new BaseDto(102,"系统繁忙,找不到合适的司机",null);
                    return baseDto;
                }
                continue;
            }


                break;
        }

//        RBucket<Object> bucket = redissonClient.getBucket("work:" + driverId);
//        Object o1 = bucket.get();
//        System.err.println(o1);



        //经过考验 派到司机了

        //修改订单状态 改为 301 行程中
        RMap<Object, Object> map = redissonClient.getMap("orderinfo:" + qo.getOrderId());
        RMap<Object, Object> map3 = redissonClient.getMap("driverinfo:" + driverId);
        map.put("orderStatus",301);
        map.put("driverId",driverId);
        map.put("driverTel",map3.get("driverTel"));
        try {
            List<OrderPojo> pojos = new ArrayList<>();
            OrderPojo o = new OrderPojo();
            o.setOrderId((String) map.get("orderId"));
            o.setPassengerId(Integer.valueOf((String) map.get("passengerId")));
            o.setOrderStatus(Integer.valueOf((String) map.get("orderStatus")));
            o.setOrderCost((Double.parseDouble((String) map.get("orderCost"))));
            o.setOrderMileage((Double.parseDouble((String) map.get("orderMileage"))) );
            o.setDriverId((Integer.valueOf((String) map.get("driverId"))));
            o.setStartName((String) map.get("startName"));
            o.setEndName((String) map.get("endName"));
//            (Date) orderMap.get("orderStatustime")
//            new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse("2019-01-03 10:59:27")

            o.setOrderStatustime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse((String)map.get("orderStatustime")));
            o.setOrderStatus((Integer.valueOf((String) map.get("orderStatus"))));

//            redissonClient.getBucket("pend:")

            QueryWrapper queryWrapper = new QueryWrapper();



            int i = orderPojoMapper.updateById(o);
            if (i==1){
                pojos.add(o);
                baseDto = new BaseDto(201,"成功派单！",pojos);
            }else {
                baseDto = new BaseDto(202,"数据库这有问题",null);
            }



        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return baseDto;
    }


}




